Item6-若不想使用编译器自动生成的函数,就该明确拒绝
Item6-若不想使用编译器自动生成的函数,就该明确拒绝
拒绝编译器自动提供的机制
通过显式声明一个成员函数,可以防止编译器生成它自己的版本,而且将这个函数声明为私有的,可以防止别人调用它。
一般而言这个做法并不绝对安全,因为member 函数和友元函数还是能够调用你的 private 函数。除非你十分聪明地不定义它们,那么,当有人不小心地调用了它们,在 link-time(链接时)会出现一个连接错误(linkage error)。
“将成员函数声明为 private 而且故意不实现它们”这一伎俩被大多数人接受,因而被用在 C++ iostream 程序库中阻止 copying 行为。
class HomeForSale {
public:
...
private:
...
//@ declarations only
HomeForSale(const HomeForSale&); //参数名称并非必要,当这个函数不实现了也就没必要写出来了
HomeForSale& operator=(const HomeForSale&);
};
通常会专门设计一个阻止 copying 动作的 base class 内:
class Uncopyable {
protected:
Uncopyable() {}
~Uncopyable() {}
private:
//@but prevent copying
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
阻止 HomeForSale 对象被拷贝,唯一需要做的就是继承 Uncopyable:
class HomeForSale: private Uncopyable {
...
};
这样行得通,因为只要任何人(包括member 函数或 friend 函数)尝试拷贝 HomeForSale 对象,编译器便尝试着生成一个 copy 构造函数和一个 copy assignment 操作符,这些编译器生成的函数会尝试调用基类的对应函数,而这些调用将被拒绝,因为基类的拷贝函数是 private的。
Uncopyable 的实现和使用颇为微妙:
- 从 Uncopyable 继承不必是 public的
- Uncopyable 的 析构函数不必是 virtual 的。因为 Uncopyable 不包含数据
总结
为了驳回编译器自动(暗自)提供的机能,将相应的成员函数声明为 private 并且不予实现
使用像 Uncopyable 这样的基类也是一种做法